'use strict';

const Controller = require('../lib/controller');
const xml2js = require('xml2js');

module.exports = class ArticleController extends Controller {
  async index() {
    switch (String(this.ctx.request.query.act)) {
      case 'new':
        await this.articleNew(false);
        break;
      case 'save':
        await this.articleNew(true);
        break;
      case 'edit':
        await this.articleEdit(false);
        break;
      case 'update':
        await this.articleEdit(true);
        break;
      case 'delete':
        await this.articleDelete();
        break;
      default:
        await this.articleView();
    }
  }

  // View Article Rountines ----------------------
  async articleView() {
    const theArticle = this.ctx.service.article;
    const strError = await theArticle.loadByID(this.ctx.request.query.id);
    if (strError != false) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    /*if (!this.ctx.theUser.checkViewPermission(theArticle)) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights_view'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }*/

    this.ctx.genSecurityCode();

    // Load article data
    await theArticle.loadSideArticle();

    // Load Comments data
    const bTimeOrder = this.ctx.app.theCache.settings.commentTimeOrder == 1;
    const bWithTrackBack = this.ctx.app.theCache.settings.showTrackbackWithComment == 1;
    const intTrackbackPos = this.ctx.app.theCache.settings.showTrackbackPosition;
    const intPageSize = this.ctx.app.theCache.settings.commentPerPage;
    let intEntryCount = 0;

    // Check current page number
    if (this.ctx.request.query.page) {
      this.ctx.request.query.page = this.ctx.helper.checkInt(this.ctx.request.query.page);
      if (this.ctx.request.query.page <= 0) {
        this.ctx.request.query.page = 1;
      }
    } else {
      this.ctx.request.query.page = 1;
    }

    intEntryCount = await theArticle.loadComments(bTimeOrder, bWithTrackBack, intTrackbackPos, intPageSize, this.ctx.request.query.page);

    // Generate the calendar for that month
    if (this.ctx.app.theCache.settings.enableDynamicCalendar == 1
      && (theArticle.postTime.getMonth() != (new Date()).getMonth())) {
      this.ctx.app.theCache.calendarHTML = await this.ctx.app.theCache.generateCalendar(theArticle.postTime.getFullYear(), theArticle.postTime.getMonth() + 1);
    }

    await this.ctx.app.connBlog.updateSQL('blog_article', {
      log_viewCount: this.ctx.app.connBlog.literal('log_viewCount+1'),
    }, {
      log_id: theArticle.id,
    });
    await this.ctx.app.theCache.updateArticleCounter(theArticle.id, 'view', 1);

    const data = {
      strTitle: theArticle.title,
      theArticle,
      intEntryCount,
      intPageSize,
      intCurrentPage: this.ctx.request.query.page,
    };

    await this.ctx.render('article/article.ejs', data);
  }

  // New Article Rountines ----------------------
  async articleNew(bSaveFlag) {
    if (this.ctx.theUser.rights.post < 2) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }
    const theArticle = this.ctx.service.article;
    // Fill Blank Data

    if (!bSaveFlag) {
      theArticle.ubbFlags = '111111';
      // Output Edit Form
      const data = {
        strTitle: this.ctx.__('new_article'),
        formTitle: this.ctx.__('new_article') + ' [' + this.ctx.__('author') + ': ' + this.ctx.theUser.username + ']',
        formAction: '?act=save',
        objArticle: theArticle,
        bEdit: false,
      };
      return await this.ctx.render('article/form.ejs', data);
    }

    // Save Changes
    const strError = await theArticle.fillFromPost(false);
    if (strError != false) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    // Insert new article
    await theArticle.insert();

    this.ctx.rotateCsrfSecret();

    let strDone = this.ctx.__('save_done');
    let bAutoRedirect = true;

    // Do trackback if requested
    if (theArticle.trackbackURL != ''
      && this.ctx.app.theCache.settings.enableTrackbackOut == 1
      && theArticle.mode == 1) {
      const	tmpA = await this.ctx.app.connBlog.query('SELECT log_ID FROM blog_article WHERE log_authorID=' + this.ctx.theUser.id + " AND log_trackbackURL='" + theArticle.trackbackURL + "' ORDER BY log_postTime DESC", 1, 1);
      if (tmpA && tmpA.length) {
        theArticle.id = tmpA[0].log_id;

        const tbError = await this.doTrackback(
          theArticle.trackbackURL,
          this.ctx.app.theCache.settings.baseURL + '?id=' + theArticle.id,
          theArticle.title,
          theArticle.content0,
          this.ctx.app.theCache.settings.blogTitle
        );
        if (tbError == '') {
          strDone += '<br />' + this.ctx.__('trackback_done');
        } else {
          strDone += '<br /><font color="red">' + this.ctx.__('trackback_error') + ': ' + tbError + '</font>';
          bAutoRedirect = false;
        }
      }
    }

    // Update counters
    await this.ctx.app.connBlog.updateSQL('blog_user', { user_articleCount: this.ctx.app.connBlog.literal('user_articleCount+1') }, { user_id: this.ctx.theUser.id });
    await this.ctx.app.connBlog.updateSQL('blog_category', { cat_articleCount: this.ctx.app.connBlog.literal('cat_articleCount+1') }, { cat_id: theArticle.categoryID });
    await this.ctx.app.theCache.loadArticles();
    await this.ctx.app.theCache.loadCategories();
    await this.ctx.app.theCache.loadCalendar();

    // Output Message
    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      strDone,
      this.ctx.__('redirect'),
      'default.asp',
      bAutoRedirect,
      'messagebox'
    );
  }

  // Edit Article Rountines ----------------------
  async articleEdit(bSaveFlag) {
    if (this.ctx.theUser.rights.edit < 1) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    const theArticle = this.ctx.service.article;
    let strError = false;

    if (bSaveFlag) {
      // Use a simple query when save changes for better performance
      this.ctx.request.query.log_id = this.ctx.helper.checkInt(this.ctx.request.query.log_id);
      if (!this.ctx.request.query.log_id) {
        strError = this.ctx.__('invalid_parameter');
      } else {
        // Check if the article exists and load required data for saving changes
        if (await theArticle.load('log_id, log_catID, log_authorID, log_postTime, log_trackbackURL', 'log_id=' + this.ctx.request.query.log_id)) {
          strError = false;
        } else {
          strError = this.ctx.__('article_not_found');
        }
      }
    } else {
      // Load full data for Edit Form
      strError = await theArticle.loadByID(this.ctx.request.query.id);
    }

    if (strError != false) {
      // Article not found
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (this.ctx.theUser.id != theArticle.authorID && this.ctx.theUser.rights.edit < 2) {
      // Check Edit Rights Again
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (!bSaveFlag) {
      // Output Edit Form
      const data = {
        strTitle: '[' + this.ctx.__('edit') + '] ' + theArticle.title,
        formTitle: this.ctx.__('edit') + ': ' + theArticle.title + ' [' + this.ctx.__('author') + ': ' + theArticle.author + ']',
        formAction: '?act=update',
        objArticle: theArticle,
        bEdit: true,
      };
      return await this.ctx.render('article/form.ejs', data);
    }

    // Check Data
    const oldCategoryID = theArticle.category.id;
    strError = theArticle.fillFromPost(true);
    if (strError != false) {
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    // Save Changes
    await theArticle.update();

    this.ctx.rotateCsrfSecret();

    // Category Changed
    if (oldCategoryID != theArticle.category.id) {
      await this.ctx.app.connBlog.updateSQL('blog_category', {
        cat_ArticleCount: this.ctx.app.connBlog.literal('cat_ArticleCount+1')
      }, {
        cat_id: theArticle.category.id
      });
      await this.ctx.app.connBlog.updateSQL('blog_category', {
        cat_ArticleCount: this.ctx.app.connBlog.literal('cat_ArticleCount-1')
      }, {
        cat_id: oldCategoryID
      });
    }

    let strDone = this.ctx.__('update_done');
    let bAutoRedirect = true;

    // Do trackback if requested
    if (theArticle.trackbackURL != ''
      && theArticle.trackbackAgain && this.ctx.app.theCache.settings.enableTrackbackOut == 1
      && theArticle.mode == 1) {
      const tbError = await this.doTrackback(
        theArticle.trackbackURL,
        this.ctx.app.theCache.settings.baseURL + '?id=' + theArticle.id,
        theArticle.title,
        theArticle.content0,
        this.ctx.app.theCache.settings.blogTitle
      );
      if (tbError == '') {
        strDone += '<br />' + this.ctx.__('trackback_done');
      } else {
        strDone += '<br /><font color="red">' + this.ctx.__('trackback_error') + ': ' + tbError + '</font>';
        bAutoRedirect = false;
      }
    }

    await this.ctx.app.theCache.loadCategories();
    await this.ctx.app.theCache.loadArticles();
    await this.ctx.app.theCache.loadCalendar();
    await this.ctx.app.theCache.loadComments();

    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      strDone,
      this.ctx.__('redirect'),
      '?id=' + theArticle.id,
      bAutoRedirect,
      'messagebox'
    );
  }

  // Delete Article  ------------------------------------------------------
  async articleDelete() {
    if (this.ctx.theUser.rights.delete < 1) {
      // Check User Right - without DB Query
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }
    const theArticle = this.ctx.service.article;
    let strError;

    this.ctx.request.query.id = this.ctx.helper.checkInt(this.ctx.request.query.id);
    if (!this.ctx.request.query.id) {
      strError = this.ctx.__('invalid_parameter');
    } else {
      // Check if the article exists
      await theArticle.load('log_id, log_authorID, log_catID', 'log_id=' + this.ctx.request.query.id);
      strError = false;
    }

    if (strError != false) {
      // Article not found
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        strError,
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    if (this.ctx.theUser.id != theArticle.authorID && this.ctx.theUser.rights.delete < 2) {
      // Check Delete Rights Again
      return await this.ctx.response.redirectMessage(
        this.ctx.__('error'),
        this.ctx.__('no_rights'),
        this.ctx.__('goback'),
        'javascript:window.history.back();',
        false,
        'errorbox'
      );
    }

    await theArticle.doDelete();
    await this.ctx.app.connBlog.updateSQL('[blog_user]', 'user_articleCount=user_articleCount-1', 'user_id=' + theArticle.authorID);
    await this.ctx.app.connBlog.updateSQL('[blog_category]', 'cat_articleCount=cat_articleCount-1', 'cat_id=' + theArticle.categoryID);
    await this.ctx.app.theCache.loadArticles();
    await this.ctx.app.theCache.loadCategories();
    await this.ctx.app.theCache.loadCalendar();
    await this.ctx.app.theCache.loadComments();

    await this.ctx.response.redirectMessage(
      this.ctx.__('done'),
      this.ctx.__('delete_done'),
      this.ctx.__('redirect'),
      'default.asp',
      true,
      'messagebox'
    );
  }

  // Send Trackback -------------------------------------------
  async doTrackback(trackbackURL, url, title, excerpt, blogName) {
    title = this.ctx.helper.cutString(title, 100);
    excerpt = this.ctx.helper.cutString(excerpt, 252);
    blogName = this.ctx.helper.cutString(blogName, 100);

    let strError = '';
    const queryString = {
      title,
      url,
      blog_name: blogName,
      excerpt: this.ctx.helper.trimUBB(excerpt),
    };

    const result = await this.ctx.curl(trackbackURL, {
      method: 'POST',
      data: queryString,
    });

    const parser = new xml2js.Parser();

    try {
      let parsedResult = await parser.parseString(result.data.toString());
      // todo
      /* if (parsedResult.getElementsByTagName('error')[0].text != '0') {
        strError = this.ctx.helper.HTMLEncode(parsedResult.getElementsByTagName('message')[0].text);
      }*/
    } catch (e) {
      strError = this.ctx.__('parse_error');
    }

    return strError;
  }
};
